package main

import (
	"log"
	"net/http"
	_ "net/http/pprof"
	"os"
	"runtime"
	"runtime/debug"
	"runtime/pprof"
	"strings"
	"time"
)

type A struct {
	b *B
}

type B struct {
	c *C
}

type C struct {
}

func (a *A) func_a() {
	a.b.func_b()
}

func (b *B) func_b() {
	b.c.func_c()
}

func (c *C) func_c() {
	N := 100000000
	arr := []string{}
	for i := 0; i < N; i++ {
		arr = append(arr, "xxxxxxxxxx")
	}
	f, err := os.Create(os.TempDir() + "/tmp.txt")
	if err != nil {
		log.Println(err)
		return
	}
	defer f.Close()
	f.WriteString(strings.Join(arr, "\n"))
}

func main() {
	log.Println("====start====")
	var m runtime.MemStats
	runtime.ReadMemStats(&m)
	log.Println(m.Alloc)

	a := &A{
		b: &B{
			c: &C{},
		},
	}
	a.func_a()

	setupOOMListener()
	//go startHttpServer()

	time.Sleep(1 * time.Hour)
}

func startHttpServer() {
	// 启动 HTTP 服务器，注册 pprof 的 HTTP 处理函数
	log.Println(http.ListenAndServe(":8080", nil))
}

func setupOOMListener() {
	// 设置内存增长限制
	debug.SetMemoryLimit(1000000)

	// 注册处理函数，在发生 OOM 时触发
	runtime.SetFinalizer(&runtime.MemStats{}, func(s *runtime.MemStats) {
		log.Println("Memory limit exceeded. Generating pprof...")
		var m runtime.MemStats
		runtime.ReadMemStats(&m)
		log.Println(m.Alloc)

		filePath := os.TempDir() + "/oom.prof"
		log.Printf("filePath = %s \n", filePath)
		f, err := os.Create(filePath)
		if err != nil {
			log.Println(err)
			return
		}
		defer f.Close()
		// pprof.StartCPUProfile(f)
		// defer pprof.StopCPUProfile()
		if err := pprof.WriteHeapProfile(f); err != nil {
			log.Println(err)
		}
		log.Println("Memory limit exceeded. Generated pprof end.")
	})
}
